package com.aoip.telemetry.telemetry.analysis.decoder;

import com.alibaba.fastjson.JSON;
import com.aoip.telemetry.telemetry.core.analysis.decoder.Decoder;
import com.aoip.telemetry.telemetry.core.exception.MsgCodecException;
import com.aoip.telemetry.telemetry.core.redis.RedisCache;
import com.aoip.telemetry.telemetry.core.util.SpringUtil;
import com.aoip.telemetry.telemetry.datastorage.ElementDataSave;
import com.aoip.telemetry.telemetry.datastorage.service.OriginalMsgDataSaveService;
import com.aoip.telemetry.telemetry.entity.common.LogEntity;
import com.aoip.telemetry.telemetry.entity.common.OriginalMessageEntity;
import com.aoip.telemetry.telemetry.entity.common.OriginalMonitoringDataEntity;
import com.aoip.telemetry.telemetry.entity.common.TableDataEntity;
import com.aoip.telemetry.telemetry.entity.enums.*;
import com.aoip.telemetry.telemetry.entity.equipment.StInfoConfigEntity;
import com.aoip.telemetry.telemetry.entity.exception.GpAbnoInfoEntity;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 报文解析协议总入口
 *
 * @author chenbai
 * @version 1.0
 * @date 2022/3/14 9:28
 */
@Component
@Slf4j
public class MsgDecoder {
    private static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Resource
    private RedisCache redisCache;
    @Resource
    private ElementDataSave elementDataSave;
    @Resource
    private OriginalMsgDataSaveService originalMsgDataSaveService;

    /**
     * 报文解析入口
     *
     * @param originalText 原始报文
     * @author chenbai
     * @date 2022/11/27
     **/
    void decode(String originalText){
//        String[] split = originalText.split(",");
//        if (split.length < 2) {
//            log.error("原始报文格式错误：{}", originalText);
//            return;
//        }
//        String msg = split[0];
//        String protocolId = split[1];
//        ProtocolBaseEntity protocol = redisCache.getCacheObject(CacheKeyEnum.PROTOCOL + ":" + protocolId);
//        String protocolEntry = protocol.getProtocolEntry();
//        String beanName = protocolEntry.substring(0, 1).toLowerCase() + protocolEntry.substring(1);
        long begin = System.currentTimeMillis();
        OriginalMessageEntity originalMessageEntity = new OriginalMessageEntity();
        LogEntity entity = new LogEntity(LogTypeEnum.LOG_ANALYSIS);
        try {
            Decoder bean = SpringUtil.getBean("snHydrologyMessageDecode");
            Boolean ignore = bean.ignoreMessages(originalText);
            if (ignore) {
                return;
            }
            originalMessageEntity = bean.originalMsgFrame(originalText);
            String stCode = originalMessageEntity.getStCode();
            StInfoConfigEntity stInfoConfigEntity = loadNormalStList(stCode);
            if (stInfoConfigEntity == null) {
                entity.setLoggerLevel(LogLevelEnum.ERROR);
                entity.setLogMsg(MsgCodecStatusEnum.ST_NON_REGISTERED.getCode() + "测站编码为：" + stCode);
            }
            originalMessageEntity = bean.entry(originalMessageEntity);
        } catch (MsgCodecException codecException) {
            originalMessageEntity.setMsgStatus(codecException.getExceptionEnum().getCode());
            entity.setLoggerLevel(LogLevelEnum.ERROR);
            entity.setLogMsg(codecException.getMessage());
            log.error("报文错误：{}", originalText);
            collectGpAbnoInfo(originalMessageEntity.getStCode(), AbnoTypeEnum.MESSAGE_EXCEPTION, originalText);
        } catch (Exception e) {
            e.printStackTrace();
            originalMessageEntity.setMsgStatus(MsgCodecStatusEnum.ANALYSIS_FAIL.getCode());
            entity.setLoggerLevel(LogLevelEnum.ERROR);
            entity.setLogMsg(e.getMessage());
            log.error("解析错误：", e.fillInStackTrace());
            log.error("解析错误：{}", originalText);
            collectGpAbnoInfo(originalMessageEntity.getStCode(), AbnoTypeEnum.MESSAGE_EXCEPTION, originalText);
        }
        List<TableDataEntity> originalDataList = new ArrayList<>();
        long originalId = IdWorker.getId(originalMessageEntity);
        originalMessageEntity.setId(originalId);
        originalMessageEntity.setMsgText(originalText);
        TableDataEntity originalEntity = new TableDataEntity();
        originalEntity.setTableName("t_original_message");
        originalEntity.setFieldMap(originalMessageEntity2Map(originalMessageEntity));
        originalDataList.add(originalEntity);
        List<OriginalMonitoringDataEntity> monitoringDataEntityList = originalMessageEntity.getMonitoringDataList();
        if (monitoringDataEntityList != null && monitoringDataEntityList.size() > 0) {
            for (OriginalMonitoringDataEntity item : monitoringDataEntityList) {
                TableDataEntity monitoringDataEntity = new TableDataEntity();
                item.setId(IdWorker.getId(item));
                item.setOriginalMessageId(originalId);
                monitoringDataEntity.setTableName("t_original_monitoring_data");
                monitoringDataEntity.setFieldMap(originalMonitoringDataEntity2Map(item));
                originalDataList.add(monitoringDataEntity);
            }
        }
        if (originalDataList.size() > 0) {
            originalMsgDataSaveService.saveData(originalDataList);
        }
//        service.save(originalMessageEntity);
//        List<OriginalMonitoringDataEntity> monitoringDataEntityList = originalMessageEntity.getMonitoringDataList();
//        if (monitoringDataEntityList != null && monitoringDataEntityList.size() > 0) {
////            List<TableDataEntity> monitoringList = new ArrayList<>();
//            originalMessageEntity.setMonitoringDataList(monitoringDataEntityList);
//            for (OriginalMonitoringDataEntity item : monitoringDataEntityList) {
//                item.setOriginalMessageId(originalMessageEntity.getId());
//                monitoringDataService.save(item);
//            }
////            elementDataSave.saveData(monitoringList);
//        }
        List<TableDataEntity> dataList = originalMessageEntity.getTableDataEntityList();
        String stCode = originalMessageEntity.getStCode();
        if (dataList != null && dataList.size() > 0) {
            int i = elementDataSave.saveData(dataList);
            if (i <= 0) {
                log.error("入库报错报文：{}",originalText);
                collectGpAbnoInfo(stCode, AbnoTypeEnum.STORAGE_FAIL, originalText);
            }
        }
        redisCache.deleteObject(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.LAST_DATA_RECEIVED + ":" + stCode);
        redisCache.setCacheObject(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.LAST_DATA_RECEIVED + ":" + stCode, LocalDateTime.now().format(dtf));
        long end = System.currentTimeMillis();
        entity.setOriginalText(originalText);
        entity.setStCode(stCode);
        entity.setExecutionTime(end - begin);
        if (LogLevelEnum.ERROR.equals(entity.getLoggerLevel())) {
            log.error("analysis==log:{}", JSON.toJSONString(entity));
        }
        if (stCode.endsWith("11111111")) {
            log.error("解析耗时：{}：报文：{};", end - begin, originalText);
        }
    }

    /**
     * 加载未锁定且有效的测站编码。
     *
     * @return java.util.Set<java.lang.String>
     * @author chenbai
     * @date 2021/10/6
     **/
    private StInfoConfigEntity loadNormalStList(String stCode) {
        Collection<String> keys = redisCache.keys(CacheKeyEnum.STATION + ":*" + stCode);
        StInfoConfigEntity stInfoConfigEntity = redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
        if (keys == null) {
            throw new MsgCodecException(MsgCodecStatusEnum.ST_NON_REGISTERED, "测站编码为：" + stCode);
        }
        return stInfoConfigEntity;
    }

    private static Map<String, Object> originalMessageEntity2Map(OriginalMessageEntity entity) {
        Map<String, Object> map = new HashMap<>(11);
        map.put("id", entity.getId());
        map.put("st_code", entity.getStCode());
        map.put("msg_text", entity.getMsgText());
        map.put("monitoring_time", entity.getMonitoringTime());
        map.put("msg_body", entity.getMsgBody());
        map.put("msg_type", entity.getMsgType());
        map.put("msg_status", entity.getMsgStatus());
        map.put("function_code", entity.getFunctionCode());
//        map.put("port", entity.getPort());
        map.put("create_time", LocalDateTime.now());
//        map.put("error_reason", entity.getErrorReason());
        return map;
    }

    private static Map<String, Object> originalMonitoringDataEntity2Map(OriginalMonitoringDataEntity entity) {
        Map<String, Object> map = new HashMap<>(6);
        map.put("id", entity.getId());
        map.put("original_message_id", entity.getOriginalMessageId());
        map.put("monitoring_data_identifier", entity.getMonitoringDataIdentifier());
        map.put("monitoring_data_value", entity.getMonitoringDataValue());
        map.put("create_time", LocalDateTime.now());
        map.put("del_flag", "0");
        return map;
    }

    /**
     * @param stCode   测站编码
     * @param abnoType 异常类型
     * @author chenbai
     * @date 2022/9/13
     **/
    private void collectGpAbnoInfo(String stCode, AbnoTypeEnum abnoType, String detail) {
        if (!StringUtils.hasText(stCode)) {
            return;
        }
        GpAbnoInfoEntity gpAbnoInfoEntity = new GpAbnoInfoEntity();
        gpAbnoInfoEntity.setCode(stCode);
        gpAbnoInfoEntity.setAbnoType(abnoType.getCode());
        gpAbnoInfoEntity.setBeginTime(LocalDateTime.now());
        gpAbnoInfoEntity.setDetails(detail);
        redisCache.setCacheList(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + abnoType + ":" + stCode, gpAbnoInfoEntity);
    }

}
